/**
 * 事件服务
 * 负责事件创建、重复规则处理、事件实例初始化、生命周期管理
 */

import { ValidationError, NotFoundError, PermissionError } from '@services/common/errors'
import { createSuccessResult, handleServiceError } from '@services/common/utils'
import {
    CreateEventDTO,
    UpdateEventDTO,
    EventDetailDTO,
    ServiceResult,
    EventStatisticsDTO
} from '@services/common/types'
import {
    EventSettings,
    EventSettingKey,
    RecurrenceConfig,
    RecurrenceFrequency,
    TimeThresholdsConfig
} from '@functypes/EventSetting.t'
import * as eventRepo from '@repos/event/event.repo'
import * as eventRecordRepo from '@repos/event/event-record.repo'
import * as eventInstanceRepo from '@repos/event/event-instance.repo'
import * as groupRepo from '@repos/group.repo'
import { checkOrgPermission } from '@services/auth.service'
import { DEFAULT_TIME_THRESHOLDS } from '@services/common/constants'

/**
 * 创建事件（含重复规则处理）
 * @param data 事件创建信息
 * @param creatorId 创建者ID（管理员或协管）
 */
export async function createEvent(data: CreateEventDTO, creatorId: string): Promise<ServiceResult<EventDetailDTO>> {
    try {
        // 1. 验证权限
        const permissionResult = await checkOrgPermission(creatorId, data.organizationId)
        if (!permissionResult.success || !permissionResult.data) {
            throw new PermissionError('No permission to create event in this organization')
        }

        // 2. 验证事件设置
        if (data.settings) {
            validateEventSettings(data.settings)
        }

        // 3. 验证时间合法性
        if (data.startAt >= data.endAt) {
            throw new ValidationError('Event end time must be after start time')
        }

        // 4. 检查是否有重复规则
        const recurrenceSetting = data.settings?.find(s => s.key === EventSettingKey.RECURRENCE)

        if (recurrenceSetting && 'frequency' in recurrenceSetting.value) {
            // 有重复规则，生成系列事件
            return await createRecurringEvents(data, creatorId)
        } else {
            // 单次事件
            return await createSingleEvent(data)
        }
    } catch (error) {
        return handleServiceError(error)
    }
}

/**
 * 创建单次事件
 */
async function createSingleEvent(data: CreateEventDTO): Promise<ServiceResult<EventDetailDTO>> {
    const result = await eventRepo.createEventWithSettings(
        data.organizationId,
        data.title,
        data.description || '',
        { startAt: data.startAt, endAt: data.endAt },
        data.settings || []
    )

    if (!result.status || !result.data) {
        throw new ValidationError(result.message || 'Failed to create event')
    }

    const eventData = result.data.event

    return createSuccessResult(
        {
            id: eventData.id,
            title: eventData.title,
            description: eventData.description || undefined,
            startAt: eventData.startAt!,
            endAt: eventData.endAt!,
            status: eventData.status,
            settings: data.settings
        },
        'Event created successfully'
    )
}

/**
 * 创建重复事件系列
 */
async function createRecurringEvents(data: CreateEventDTO, creatorId: string): Promise<ServiceResult<EventDetailDTO>> {
    const recurrenceSetting = data.settings?.find(s => s.key === EventSettingKey.RECURRENCE) as
        | { key: EventSettingKey.RECURRENCE; value: RecurrenceConfig }
        | undefined

    if (!recurrenceSetting) {
        throw new ValidationError('Recurrence setting not found')
    }

    const recurrence = recurrenceSetting.value

    // 生成所有重复事件的日期
    const eventDates = generateRecurringDates(data.startAt, data.endAt, recurrence)

    // 边界检查
    if (eventDates.length === 0) {
        throw new ValidationError('No valid dates generated for recurring event')
    }

    if (eventDates.length > 365) {
        throw new ValidationError('Too many recurring events (max 365 per series)')
    }

    // 创建第一个事件作为主事件
    const firstEventResult = await createSingleEvent({
        ...data,
        startAt: eventDates[0].start,
        endAt: eventDates[0].end
    })

    if (!firstEventResult.success || !firstEventResult.data) {
        throw new ValidationError('Failed to create first event in series')
    }

    // 创建剩余的重复事件
    for (let i = 1; i < eventDates.length; i++) {
        await eventRepo.createEventWithSettings(
            data.organizationId,
            data.title,
            data.description || '',
            { startAt: eventDates[i].start, endAt: eventDates[i].end },
            data.settings || []
        )
    }

    return createSuccessResult(
        {
            ...firstEventResult.data,
            // 添加系列信息
            statistics: {
                totalParticipants: 0,
                presentCount: 0,
                lateCount: 0,
                absentCount: 0,
                pendingCount: 0,
                leaveEarlyCount: 0,
                attendanceRate: 0
            }
        },
        `Created ${eventDates.length} recurring events successfully`
    )
}

/**
 * 生成重复事件的日期列表
 * 核心算法：处理周几重复、月份重复等边界情况
 */
function generateRecurringDates(
    startDate: Date,
    endDate: Date,
    recurrence: RecurrenceConfig
): Array<{ start: Date; end: Date }> {
    const dates: Array<{ start: Date; end: Date }> = []
    const eventDuration = endDate.getTime() - startDate.getTime()

    let currentDate = new Date(startDate)
    let count = 0
    const maxIterations = 1000 // 防止无限循环

    // 确定结束条件
    const hasEndDate = recurrence.endDate !== undefined
    const hasOccurrences = recurrence.occurrences !== undefined
    const maxOccurrences = recurrence.occurrences || 365

    while (count < maxIterations) {
        // 检查是否达到结束条件
        if (hasEndDate && currentDate > recurrence.endDate!) {
            break
        }
        if (hasOccurrences && dates.length >= maxOccurrences) {
            break
        }
        if (!hasEndDate && !hasOccurrences && dates.length >= 365) {
            // 默认最多365次
            break
        }

        // 根据频率类型判断是否应该在这个日期创建事件
        if (shouldCreateEventOnDate(currentDate, startDate, recurrence)) {
            const eventStart = new Date(currentDate)
            const eventEnd = new Date(currentDate.getTime() + eventDuration)
            dates.push({ start: eventStart, end: eventEnd })
        }

        // 移动到下一个候选日期
        currentDate = getNextCandidateDate(currentDate, recurrence)
        count++
    }

    return dates
}

/**
 * 判断是否应该在指定日期创建事件
 */
function shouldCreateEventOnDate(date: Date, originalStart: Date, recurrence: RecurrenceConfig): boolean {
    const { frequency, interval = 1, daysOfWeek, daysOfMonth } = recurrence

    switch (frequency) {
        case RecurrenceFrequency.DAILY:
            // 每N天重复
            const daysDiff = Math.floor((date.getTime() - originalStart.getTime()) / (1000 * 60 * 60 * 24))
            return daysDiff % interval === 0

        case RecurrenceFrequency.WEEKLY:
            // 每N周的指定周几重复
            const weeksDiff = Math.floor((date.getTime() - originalStart.getTime()) / (1000 * 60 * 60 * 24 * 7))
            const dayOfWeek = date.getDay() // 0=周日, 1=周一, ..., 6=周六

            // 检查是否在正确的周
            if (weeksDiff % interval !== 0) {
                return false
            }

            // 检查是否在指定的周几
            if (daysOfWeek && daysOfWeek.length > 0) {
                return daysOfWeek.includes(dayOfWeek)
            }

            // 如果没有指定周几，默认使用原始日期的周几
            return dayOfWeek === originalStart.getDay()

        case RecurrenceFrequency.MONTHLY:
            // 每N月的指定日期重复
            const monthsDiff =
                (date.getFullYear() - originalStart.getFullYear()) * 12 + (date.getMonth() - originalStart.getMonth())

            // 检查是否在正确的月份
            if (monthsDiff % interval !== 0) {
                return false
            }

            // 检查是否在指定的日期
            if (daysOfMonth && daysOfMonth.length > 0) {
                return daysOfMonth.includes(date.getDate())
            }

            // 如果没有指定日期，默认使用原始日期
            return date.getDate() === originalStart.getDate()

        case RecurrenceFrequency.CUSTOM:
            // 自定义规则（暂时按每日处理）
            return true

        default:
            return false
    }
}

/**
 * 获取下一个候选日期
 */
function getNextCandidateDate(currentDate: Date, recurrence: RecurrenceConfig): Date {
    const { frequency } = recurrence
    const next = new Date(currentDate)

    switch (frequency) {
        case RecurrenceFrequency.DAILY:
        case RecurrenceFrequency.CUSTOM:
            // 每天检查
            next.setDate(next.getDate() + 1)
            break

        case RecurrenceFrequency.WEEKLY:
            // 每天检查（因为可能有多个周几）
            next.setDate(next.getDate() + 1)
            break

        case RecurrenceFrequency.MONTHLY:
            // 每天检查（避免跳过月底日期）
            next.setDate(next.getDate() + 1)
            break
    }

    return next
}

/**
 * 验证事件设置的合法性
 */
function validateEventSettings(settings: EventSettings[]): void {
    // 检查是否有重复的key
    const keys = settings.map(s => s.key)
    const uniqueKeys = new Set(keys)
    if (keys.length !== uniqueKeys.size) {
        throw new ValidationError('Duplicate setting keys found')
    }

    // 验证时间阈值
    const thresholdSetting = settings.find(s => s.key === EventSettingKey.TIME_THRESHOLDS)
    if (thresholdSetting && 'gracePeriodMinutes' in thresholdSetting.value) {
        const thresholds = thresholdSetting.value as TimeThresholdsConfig

        if (thresholds.gracePeriodMinutes < 0) {
            throw new ValidationError('Grace period cannot be negative')
        }
        if (thresholds.lateThresholdMinutes < thresholds.gracePeriodMinutes) {
            throw new ValidationError('Late threshold must be greater than grace period')
        }
        if (thresholds.absentThresholdMinutes < thresholds.lateThresholdMinutes) {
            throw new ValidationError('Absent threshold must be greater than late threshold')
        }
    }

    // 验证重复规则
    const recurrenceSetting = settings.find(s => s.key === EventSettingKey.RECURRENCE)
    if (recurrenceSetting && 'frequency' in recurrenceSetting.value) {
        const recurrence = recurrenceSetting.value as RecurrenceConfig

        if (recurrence.interval !== undefined && recurrence.interval < 1) {
            throw new ValidationError('Recurrence interval must be at least 1')
        }

        if (recurrence.daysOfWeek) {
            // 验证周几的值在 0-6 之间
            if (recurrence.daysOfWeek.some(day => day < 0 || day > 6)) {
                throw new ValidationError('Invalid day of week (must be 0-6)')
            }
            // 去重并排序
            recurrence.daysOfWeek = [...new Set(recurrence.daysOfWeek)].sort()
        }

        if (recurrence.daysOfMonth) {
            // 验证日期的值在 1-31 之间
            if (recurrence.daysOfMonth.some(day => day < 1 || day > 31)) {
                throw new ValidationError('Invalid day of month (must be 1-31)')
            }
            // 去重并排序
            recurrence.daysOfMonth = [...new Set(recurrence.daysOfMonth)].sort()
        }

        // endDate 和 occurrences 不能同时设置
        if (recurrence.endDate && recurrence.occurrences) {
            throw new ValidationError('Cannot set both endDate and occurrences')
        }
    }
}

/**
 * 初始化事件参与者的 EventInstance
 * @param eventId 事件ID
 * @param participantIds 参与者ID列表（成员ID或组ID）
 * @param participantType 参与者类型（member或group）
 */
export async function initializeEventInstances(
    eventId: string,
    participantIds: string[],
    participantType: 'member' | 'group'
): Promise<ServiceResult<number>> {
    try {
        // 1. 验证事件存在
        const eventResult = await eventRepo.readEvent(eventId)
        if (!eventResult.status || !eventResult.data) {
            throw new NotFoundError('Event')
        }

        const event = eventResult.data

        // 2. 获取所有成员ID
        let memberIds: string[] = []

        if (participantType === 'member') {
            memberIds = participantIds
        } else {
            // 从组中获取所有成员
            for (const groupId of participantIds) {
                const groupMembersResult = await groupRepo.readGroupMemberList(groupId, 0, 1000, false)
                if (groupMembersResult.status && groupMembersResult.data) {
                    const members = groupMembersResult.data.result.map((mg: any) => mg.member.id)
                    memberIds.push(...members)
                }
            }
            // 去重
            memberIds = [...new Set(memberIds)]
        }

        // 边界检查
        if (memberIds.length === 0) {
            throw new ValidationError('No members to initialize')
        }

        if (memberIds.length > 10000) {
            throw new ValidationError('Too many members (max 10000 per event)')
        }

        // 3. 批量创建 EventInstance（不创建 EventRecord，等待签到时创建）
        const result = await eventInstanceRepo.createEventInstanceBatch(
            eventId,
            memberIds,
            event.organizationId,
            false // 非周期性
        )

        if (!result.status) {
            throw new ValidationError('Failed to create event instances')
        }

        return createSuccessResult(memberIds.length, `Initialized ${memberIds.length} event instances`)
    } catch (error) {
        return handleServiceError(error)
    }
}

/**
 * 获取事件详情（含统计信息）
 */
export async function getEventDetail(eventId: string): Promise<ServiceResult<EventDetailDTO>> {
    try {
        // 1. 获取事件基本信息
        const eventResult = await eventRepo.readEvent(eventId)
        if (!eventResult.status || !eventResult.data) {
            throw new NotFoundError('Event')
        }

        const event = eventResult.data

        // 2. 获取签到统计
        const statsResult = await eventRecordRepo.getEventRecordStatistics(eventId)

        let statistics: EventStatisticsDTO = {
            totalParticipants: 0,
            presentCount: 0,
            lateCount: 0,
            absentCount: 0,
            pendingCount: 0,
            leaveEarlyCount: 0,
            attendanceRate: 0
        }

        if (statsResult.status && statsResult.data) {
            const stats = statsResult.data
            statistics = {
                totalParticipants: stats.total || 0,
                presentCount: stats.present || 0,
                lateCount: stats.late || 0,
                absentCount: stats.absent || 0,
                pendingCount: stats.pending || 0,
                leaveEarlyCount: stats.leaveEarly || 0,
                attendanceRate: stats.total > 0 ? Math.round(((stats.present || 0) / stats.total) * 100 * 100) / 100 : 0
            }
        }

        // 3. 解析设置
        const settings =
            event.EventSetting && event.EventSetting.length > 0
                ? (event.EventSetting[0].value as EventSettings[])
                : undefined

        return createSuccessResult(
            {
                id: event.id,
                title: event.title,
                description: event.description || undefined,
                startAt: event.startAt!,
                endAt: event.endAt!,
                status: event.status,
                settings,
                statistics
            },
            'Event detail retrieved'
        )
    } catch (error) {
        return handleServiceError(error)
    }
}

/**
 * 更新事件
 */
export async function updateEvent(
    eventId: string,
    data: UpdateEventDTO,
    updaterId: string
): Promise<ServiceResult<EventDetailDTO>> {
    try {
        // 1. 验证事件存在
        const eventResult = await eventRepo.readEvent(eventId)
        if (!eventResult.status || !eventResult.data) {
            throw new NotFoundError('Event')
        }

        const event = eventResult.data

        // 2. 验证权限
        const permissionResult = await checkOrgPermission(updaterId, event.organizationId)
        if (!permissionResult.success || !permissionResult.data) {
            throw new PermissionError('No permission to update this event')
        }

        // 3. 验证时间合法性
        const newStart = data.startAt || event.startAt!
        const newEnd = data.endAt || event.endAt!
        if (newStart >= newEnd) {
            throw new ValidationError('Event end time must be after start time')
        }

        // 4. 验证设置
        if (data.settings) {
            validateEventSettings(data.settings)
        }

        // 5. 更新事件
        const updateResult = await eventRepo.updateEventWithSettings(
            eventId,
            data.title || event.title,
            data.description !== undefined ? data.description : event.description || '',
            { startAt: newStart, endAt: newEnd },
            data.settings || []
        )

        if (!updateResult.status || !updateResult.data) {
            throw new ValidationError('Failed to update event')
        }

        return getEventDetail(eventId)
    } catch (error) {
        return handleServiceError(error)
    }
}

/**
 * 删除事件
 */
export async function deleteEvent(eventId: string, deleterId: string): Promise<ServiceResult<boolean>> {
    try {
        // 1. 验证事件存在
        const eventResult = await eventRepo.readEvent(eventId)
        if (!eventResult.status || !eventResult.data) {
            throw new NotFoundError('Event')
        }

        const event = eventResult.data

        // 2. 验证权限
        const permissionResult = await checkOrgPermission(deleterId, event.organizationId)
        if (!permissionResult.success || !permissionResult.data) {
            throw new PermissionError('No permission to delete this event')
        }

        // 3. 删除事件（软删除）
        const deleteResult = await eventRepo.deleteEvent(eventId)

        if (!deleteResult.status) {
            throw new ValidationError('Failed to delete event')
        }

        return createSuccessResult(true, 'Event deleted successfully')
    } catch (error) {
        return handleServiceError(error)
    }
}

/**
 * 获取事件的时间阈值配置（如果没有则返回默认值）
 */
export function getEventTimeThresholds(settings?: EventSettings[]): TimeThresholdsConfig {
    if (!settings) {
        return DEFAULT_TIME_THRESHOLDS
    }

    const thresholdSetting = settings.find(s => s.key === EventSettingKey.TIME_THRESHOLDS)

    if (thresholdSetting && 'gracePeriodMinutes' in thresholdSetting.value) {
        return thresholdSetting.value as TimeThresholdsConfig
    }

    return DEFAULT_TIME_THRESHOLDS
}
